// GI 包括接受烘焙，所以自己本身也要能接收和生成阴影
Shader "URP/URPGI"
{
	Properties
	{
		_BaseColor("Base Color",color) = (1,1,1,1)
		_BaseMap("BaseMap", 2D) = "white" {}
	}

	SubShader
	{
		Tags { "Queue"="Geometry" "RenderType" = "Opaque" "IgnoreProjector" = "True" "RenderPipeline" = "UniversalPipeline" }
		LOD 100

		Pass
		{
			Name "Unlit"
			HLSLPROGRAM
			// Required to compile gles 2.0 with standard srp library
			#pragma prefer_hlslcc gles
			#pragma exclude_renderers d3d11_9x
			#pragma vertex vert
			#pragma fragment frag
			#pragma multi_compile_fog
			#pragma multi_compile LIGHTMAP_OFF LIGHTMAP_ON
			// 接收阴影
			#pragma multi_compile _ _MAIN_LIGHT_SHADOWS
			#pragma multi_compile _ _SHADOWS_SOFT
			#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Color.hlsl"
			#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
			//#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
			#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/UnityInstancing.hlsl"
			#include "../MyHLSL/MyLighting.hlsl"

			struct Attributes
			{
				float4 positionOS   : POSITION;
				float3 normalOS     : NORMAL;
				float4 tangentOS    : TANGENT;
				float2 texcoord     : TEXCOORD0;
				float2 lightmapUV   : TEXCOORD1;
			};

			struct Varyings
			{
				float2 uv                       : TEXCOORD0;
				// 这里定义了光照贴图和球谐，这里也是需要的，
				DECLARE_LIGHTMAP_OR_SH(lightmapUV, vertexSH, 1);
				float3 normalWS                 : TEXCOORD2;
				float3 viewDirWS                : TEXCOORD3;
				half4 fogFactorAndVertexLight   : TEXCOORD4; // x: fogFactor, yzw: vertex light
				float4 positionCS               : SV_POSITION;
				half4 shadowCoord              : TEXCOORD5;
			};

			CBUFFER_START(UnityPerMaterial)
			half4 _BaseColor;
			float4 _BaseMap_ST;
			CBUFFER_END
			TEXTURE2D (_BaseMap);SAMPLER(sampler_BaseMap);
			// #define smp _linear_clampU_mirrorV
			// SAMPLER(smp);

			Varyings vert(Attributes v)
			{
				Varyings o = (Varyings)0;

				o.positionCS = TransformObjectToHClip(v.positionOS.xyz);
				o.uv = TRANSFORM_TEX(v.texcoord, _BaseMap);
				half3 positionWS = TransformObjectToWorld(v.positionOS.xyz);
				half3 positionCS = TransformWorldToHClip(positionWS).xyz;
				o.normalWS = TransformObjectToWorldNormal(v.normalOS);
				o.viewDirWS = GetWorldSpaceViewDir(positionWS);
				OUTPUT_LIGHTMAP_UV(v.lightmapUV, unity_LightmapST, o.lightmapUV);
				OUTPUT_SH(o.normalWS.xyz, o.vertexSH);

				half3 vertexLight = VertexLighting(positionWS, o.normalWS);
				half fogFactor = ComputeFogFactor(positionCS.z);
				o.fogFactorAndVertexLight = half4(fogFactor, vertexLight);
				o.shadowCoord = TransformWorldToShadowCoord(positionWS);
				return o;
			}

			half4 frag(Varyings i) : SV_Target
			{
				half4 c;
				half4 baseMap = SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, i.uv);
				c = baseMap * _BaseColor;
				// 没用的东西感觉是 可以不要
				// #ifdef _SPECULARHIGHLIGHTS_OFF
				// 	bool specularHighlightsOff = true;
				// #else
				//     bool specularHighlightsOff = false;
				// #endif

				SurfaceData surfaceData = (SurfaceData)0;
				surfaceData.alpha = 1;
				surfaceData.albedo = 1;
				surfaceData.metallic = 0;
				surfaceData.specular = half3(0.0h, 0.0h, 0.0h);
				surfaceData.smoothness = 0;
				surfaceData.clearCoatMask       = 0.0h;
				surfaceData.clearCoatSmoothness = 0.0h;
				surfaceData.occlusion = 1;

				InputData inputData = (InputData)0;
				half3 viewDirWS = SafeNormalize(i.viewDirWS);
				inputData.normalWS = i.normalWS;
				inputData.normalWS = NormalizeNormalPerPixel(inputData.normalWS);
				inputData.viewDirectionWS = viewDirWS;
				inputData.shadowCoord = i.shadowCoord;
				inputData.fogCoord = i.fogFactorAndVertexLight.x;
				inputData.vertexLighting = i.fogFactorAndVertexLight.yzw;
				inputData.bakedGI = SAMPLE_GI(i.lightmapUV, i.vertexSH, inputData.normalWS);
				inputData.normalizedScreenSpaceUV = GetNormalizedScreenSpaceUV(i.positionCS);
				inputData.shadowMask = SAMPLE_SHADOWMASK(i.lightmapUV);
				//brdfData
				BRDFData brdfData = (BRDFData)0;
				InitializeBRDFData(surfaceData.albedo, surfaceData.metallic, surfaceData.specular, surfaceData.smoothness, surfaceData.alpha, brdfData);
				BRDFData brdfDataClearCoat = (BRDFData)0;

				Light mainLight = GetMainLight(inputData.shadowCoord, inputData.positionWS, inputData.shadowMask);
				MixRealtimeAndBakedGI(mainLight, inputData.normalWS, inputData.bakedGI);

				// half3 col = SubtractDirectMainLightFromLightmap(mainLight, inputData.normalWS, inputData.bakedGI);
				// half3 attenuatedLightColor = mainLight.color * (mainLight.distanceAttenuation * mainLight.shadowAttenuation);
				//return half4(attenuatedLightColor.rgb,1);
				//return half4(inputData.bakedGI,1);
				half3 colorGI = GlobalIllumination(brdfData,brdfDataClearCoat,surfaceData.clearCoatMask,inputData.bakedGI,surfaceData.occlusion,i.normalWS,viewDirWS);
				// LightingPhysicallyBased 里面修改了阴影的一些计算，使得阴影柔化
				colorGI += LightingPhysicallyBased(brdfData, brdfDataClearCoat,mainLight,inputData.normalWS, inputData.viewDirectionWS,
				surfaceData.clearCoatMask, true);  // specularHighlightsOff
				
				c.rgb *= colorGI;

				return c;
			}
			
			ENDHLSL
		}
		// 生成阴影
		Pass
		{
			Name "ShadowCaster"
			Tags{"LightMode" = "ShadowCaster"}

			ZWrite On
			ZTest LEqual
			//Cull[_Cull]

			HLSLPROGRAM
			// Required to compile gles 2.0 with standard srp library
			// #pragma prefer_hlslcc gles
			// #pragma exclude_renderers d3d11_9x
			#pragma target 2.0

			// -------------------------------------


			//--------------------------------------
			// GPU Instancing
			#pragma multi_compile_instancing

			#pragma vertex vert
			#pragma fragment frag

			#include "Packages/com.unity.render-pipelines.universal/Shaders/SimpleLitInput.hlsl"
			#include "Packages/com.unity.render-pipelines.universal/Shaders/ShadowCasterPass.hlsl"

			struct appdata
			{
				float4 positionOS   : POSITION;
				float3 normalOS     : NORMAL;
				float2 texcoord     : TEXCOORD0;
				UNITY_VERTEX_INPUT_INSTANCE_ID
			};

			struct v2f
			{
				float2 uv           : TEXCOORD0;
				float4 positionCS   : SV_POSITION;
			};


			v2f vert(appdata input)
			{
				v2f output;
				UNITY_SETUP_INSTANCE_ID(input);

				output.uv = TRANSFORM_TEX(input.texcoord, _BaseMap);
				//output.positionCS = TransformObjectToHClip(input.positionOS.xyz);
				// GetShadowPositionHClip 这个不加就会有摩尔纹(锯齿)
				output.positionCS = GetShadowPositionHClip(input);
				return output;
			}

			half4 frag(v2f input) : SV_TARGET
			{
				//Alpha(SampleAlbedoAlpha(input.uv, TEXTURE2D_ARGS(_BaseMap, sampler_BaseMap)).a, _BaseColor, _Cutoff);
				return 0;
			}

			ENDHLSL
		}

		// 接受烘焙
		Pass
		{
			Name "Meta"
			Tags{"LightMode" = "Meta"}

			Cull Off

			HLSLPROGRAM
			#pragma exclude_renderers gles gles3 glcore
			#pragma target 3.5

			#pragma vertex UniversalVertexMeta
			#pragma fragment UniversalFragmentMeta

			#pragma shader_feature_local_fragment _SPECULAR_SETUP
			#pragma shader_feature_local_fragment _EMISSION
			#pragma shader_feature_local_fragment _METALLICSPECGLOSSMAP
			#pragma shader_feature_local_fragment _ALPHATEST_ON
			#pragma shader_feature_local_fragment _ _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
			#pragma shader_feature_local _ _DETAIL_MULX2 _DETAIL_SCALED

			#pragma shader_feature_local_fragment _SPECGLOSSMAP

			#include "Packages/com.unity.render-pipelines.universal/Shaders/LitInput.hlsl"
			#include "Packages/com.unity.render-pipelines.universal/Shaders/LitMetaPass.hlsl"

			ENDHLSL
		}
	}
}
